package com.webside.api.config;

import com.alibaba.fastjson.JSON;
import com.webside.util.IPUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.logging.log4j.core.config.Order;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 统一日志处理
 *
 * @author wjggwm
 * @version 1.0.0
 * @date 2019/1/6  23:36
 */
@Slf4j
@Aspect
@Component
@Order(1)
public class LogAspect {

    //申明一个切点 里面是 execution表达式,两个..代表所有子目录，最后括号里的两个..代表所有参数
    @Pointcut("execution(public * com.webside.api.controller.*..*(..))")
    private void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Object logHandler(ProceedingJoinPoint process) throws Throwable {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        StopWatch stopWatch = StopWatch.createStarted();
        long startTime =stopWatch.getTime();
        MethodSignature methodSignature = (MethodSignature) process.getSignature();
        Method method = methodSignature.getMethod();
        String url = request.getRequestURL().toString();
        String httpMethod = request.getMethod();
        String methodName = method.getName();
        String className = method.getDeclaringClass().getName();
        Object[] args = process.getArgs();
        List<Object> argsList = filterArgs(args);
        String ip = IPUtils.getIpAddr(request);
        Object result = process.proceed();
        stopWatch.stop();
        long endTime = stopWatch.getTime();
        log.info("\nIP：{}\n请求地址：{}\n请求方式：{}\n请求类名：{}\n请求方法：{}\n请求参数：{}\n请求结果：{}\n请求开始时间：{}\n请求结束时间：{}\n请求耗时：{}毫秒",
                ip, url, httpMethod, className, methodName, JSON.toJSON(argsList), JSON.toJSON(result),
                DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss.S"),
                DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss.S"),
                endTime - startTime);
        return result;
    }

    private List<Object> filterArgs(Object[] args) {
        List<Object> argsList = new ArrayList<>();
        for (Object arg : args) {
            if (!(arg instanceof MultipartFile || arg instanceof HttpServletResponse
                    || arg instanceof HttpServletRequest)) {
                argsList.add(arg);
            }
        }
        return argsList;
    }

}

